package estrategias;

import java.util.Date;
import java.util.Random;
import java.util.Vector;

import juegos.*;

/**
 * 
 * @author DaNieLooP
 *
 */
public class EnfriamientoSimulado implements Estrategia {

	/**
	 * metodo que resuelve un problema por enfriamiento simulado.
	 * @param inicial nodo inicial
	 * @param nFinal nodo final
	 * @return nodo al que llegamos
	 */
	public Nodo resuelve(Nodo inicial,Nodo nFinal) {
		int generados = 1;
		int expandidos = 0;
		Date inicio = new Date();
		boolean enc = false;
		Random r = new Random();
		Vector v=new Vector(0,1);
		int i;
		int e;
		double P;
		boolean encint=false;
		double T;
		Nodo actual;
		Nodo nuevoEstado;
		Nodo mejorHastaAhora;
		if(inicial.esFinal()){
			return inicial;
		}else{
			actual = inicial;
			mejorHastaAhora = actual;
			// TODO ver temperaturas iniciales y enfriamientos
			T = 10;
		}
		v.add(inicial);
		while(!v.isEmpty()&&!enc){
			i=0;
			v.removeAllElements();
			v = actual.generaHijos();
			expandidos++;
			generados = generados + v.size();
			nuevoEstado =(Nodo) v.elementAt(r.nextInt(v.size()));
			e=nuevoEstado.getVHeur()-actual.getVHeur();
			if(nuevoEstado.esFinal()){
				Date fin = new Date();
				float total = (fin.getTime()-inicio.getTime())/1000f;
				String saux = nuevoEstado.getCamino()+'\n'+"Nodos generados: "+generados+'\n'+"Nodos expandidos: "+expandidos+
				'\n'+"Tiempo transcurrido: "+total+" segundos"+'\n'+"Profundidad: "+nuevoEstado.getProfundidad()+'\n'+"Coste: "+nuevoEstado.getCoste();
				nuevoEstado.setCamino(saux);
				return nuevoEstado;
			}else{
				if(nuevoEstado.getVHeur()<actual.getVHeur()){
					actual = nuevoEstado;
					if(nuevoEstado.getVHeur()<mejorHastaAhora.getVHeur()){
						mejorHastaAhora = nuevoEstado;
					}
				}else{
					P=Math.pow((double) Math.E, (double)-(e/T));
					if(Math.random()<P){
						actual = nuevoEstado;
					}
				}
			}
		T = T-0.01;	
		if(T<0){
			return null;
		}
		}
		return mejorHastaAhora;
	}
	/**
	 * main para probar la estrategia
	 * @param args
	 */
	public static void main(String[] args) {
		NodoColores n = new NodoColores();
		EnfriamientoSimulado p = new EnfriamientoSimulado();
		NodoColores re = (NodoColores) p.resuelve(n,n);
		if(re==null){
			System.out.println("no hay solucion");
		}else{
			System.out.println(re.getCamino());
		}
	}

}
